package pe.gob.essalud.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pe.gob.essalud.dao.EmpresaDAO;
import pe.gob.essalud.dao.PersonaDAO;
import pe.gob.essalud.dao.UsuarioDAO;
import pe.gob.essalud.model.Permiso;
import pe.gob.essalud.model.Usuario;
import pe.gob.essalud.service.UsuarioService;

@Service
public class UsuarioServiceImpl implements UsuarioService {
	
	@Resource
	private UsuarioDAO usuarioDAO;
	
	@Resource
	private EmpresaDAO empresaDAO;
	
	@Resource
	private PersonaDAO personaDAO;
	
	@Autowired
	private ShaPasswordEncoder passwordEncoder;

	@Transactional
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		Usuario usuario = usuarioDAO.buscarPorLogin(username);

		if (usuario == null){
			throw new UsernameNotFoundException("El usuario no existe");
		}			

		List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
		for(Permiso permiso : usuario.getPerfil().getPermisos()){
			authorities.add(new SimpleGrantedAuthority(permiso.getAutoridad()));
		}

		return new User(usuario.getLogin(), usuario.getPassword(), usuario.isFlagActivo(), true, true, !usuario.isFlagBaja(), authorities);
	}
	
	@Transactional(readOnly = true)
	public Usuario buscarUsuario(Integer idUsuario) {
		return usuarioDAO.findOne(idUsuario);
	}

	@Transactional(readOnly = true)
	public List<Usuario> buscarTodos() {
		return usuarioDAO.buscarHabilitados();
	}

	@Transactional
	public Usuario registrarUsuario(Usuario usuario) {
		Usuario nuevo = new Usuario();
		nuevo.setFlagActivo(usuario.isFlagActivo());
		nuevo.setCorreo(usuario.getCorreo());
		nuevo.setFlagBaja(false);
		nuevo.setLogin(usuario.getLogin());
		nuevo.setPassword(encriptarPassword(usuario.getPassword()));
		nuevo.setPerfil(usuario.getPerfil());
		nuevo.setTipo(usuario.getTipo());
		if(usuario.getEmpresa().getId() != null){
			nuevo.setEmpresa(empresaDAO.findOne(usuario.getEmpresa().getId()));
		}
		if(usuario.getPersona().getId() != null){
			nuevo.setPersona(personaDAO.findOne(usuario.getPersona().getId()));
		}
		return usuarioDAO.save(nuevo);
	}
	
	@Transactional
	public Usuario editarUsuario(Usuario usuario) {
		Usuario editado = usuarioDAO.findOne(usuario.getId());
		editado.setFlagActivo(usuario.isFlagActivo());
		editado.setCorreo(usuario.getCorreo());
		editado.setLogin(usuario.getLogin());
		editado.setTipo(usuario.getTipo());
		editado.setPerfil(usuario.getPerfil());
		if(usuario.getEmpresa().getId() != null){
			editado.setEmpresa(empresaDAO.findOne(usuario.getEmpresa().getId()));
		} else {
			editado.setEmpresa(null);
		}
		if(usuario.getPersona().getId() != null){
			editado.setPersona(personaDAO.findOne(usuario.getPersona().getId()));
		} else {
			editado.setPersona(null);
		}
		return usuarioDAO.save(editado);
	}

	@Transactional
	public void darBajaUsuario(Integer idUsuario){
		Usuario usuario = usuarioDAO.findOne(idUsuario);
		usuario.setFlagBaja(true);
		usuarioDAO.save(usuario);
	}
	
	@Transactional
	public void cambiarPasswordUsuario(Integer idUsuario, String password){
		Usuario usuario = usuarioDAO.findOne(idUsuario);
		usuario.setPassword(encriptarPassword(password));
		usuarioDAO.save(usuario);
	}
	
	@Transactional(readOnly = true)
	public boolean isLoginRepetido(String login, Integer idUsuario) {
		Usuario u = usuarioDAO.buscarPorLogin(login);
		if(u != null && u.getId() != idUsuario){			
			return true;
		} else {
			return false;
		}
	}
	
	private String encriptarPassword(String password){
		return passwordEncoder.encodePassword(password, null);
	}
}
